package ig.finanzas;

import ig.util.excepciones.DatoInvalidoExcepcion;
import java.io.Serializable;

/**
 * Define la forma en que se debe calcular el cambio esperado para una serie
 * de valores. Basicamente existen solo 4 formas para definir la forma de calculo
 * del cambio esperado
 * <ul>
 *   <li>Utilizar como cambio esperado un valor fijo especificado.</li>
 *   <li>Calcular la desviacion estandar de la serie de valores utilizando EWMA.</li>
 *   <li>Calcular la desviacion estandar de la serie de valores.</li>
 *   <li>Calcular el cambio esperado utilizando el metodo de diferencias.</li>
 * </ul> 
 * <br>
 * Generalmente ademas de definir como se debe calcular el cambio esperado tambien se debe especificar
 * el coeficiente de confianza para el que se desea obtener la respuesta. 
 * <br>
 * @author lfgarcia
 */
public class DefinidorCalculoCambioEsperado implements Serializable {
	static final long serialVersionUID = 01;
	public static final byte FORMA_CALCULOCAMBIOESPERADO_VALORESPECIFICADO  = 1;
	public static final byte FORMA_CALCULOCAMBIOESPERADO_EWMA = 2;
	public static final byte FORMA_CALCULOCAMBIOESPERADO_NORMAL = 3;
	public static final byte FORMA_CALCULOCAMBIOESPERADO_ELIECER = 4;
	public static final byte FORMA_CALCULOCAMBIOESPERADO_ELIECER_NO_SUMAR_PROMEDIO = 5;
        public static final byte FORMA_CALCULOCAMBIOESPERADO_ELIECER_NO_SUMAR_PROMEDIO_MAX_OBSERVACION = 6;
        public static final byte FORMA_VALORACION_HISTORICA = 8;
        public static final byte FORMA_REGRESION_LINIAL = 9;
        
	public static final byte DIF_ARITMETICA = 0;
	public static final byte DIF_LOGARITMICA = 1;
        /*
         * Modificado por Cristhiam Reina
         * 5 de agosto 2011
         * Atributo nuevo
         */
        public static final byte DIF_GEOMETRICA = 2;
        /*
         * Modificado por Eliecer Cortes
         * 2 de Septiembre 2011
         * Atributo nuevo
         */
        public static final byte NO_CALCULAR_DIF = 3;


		
	/**
	 * @uml.property  name="formaCalculoCambioEsperado"
	 */

	private byte formaCalculoCambioEsperado;
		//Para el caso de valor especificado
		/**
		 * @uml.property  name="valor"
		 */
		private double valor;
		/**
		 * @uml.property  name="numdias"
		 */
		private int numdias;
		//Atributos comunes
		/**
		 * @uml.property  name="numobservaciones"
		 */
		private int numobservaciones;
		/**
		 * @uml.property  name="coeficienteconfianza"
		 */
		private double coeficienteconfianza;
		//Para el caso ewma
		/**
		 * @uml.property  name="lambda"
		 */
		private double lambda;
		//Para el caso eliecer
		/**
		 * @uml.property  name="tipodiferencia"
		 */
		private byte tipodiferencia;
		/**
		 * @uml.property  name="longperiodo"
		 */
		private int longperiodo;

	/**
	 * Crea un objeto que define el cambio esperado como un valor fijo que se especifique.
	 * @param valor
	 */
	public DefinidorCalculoCambioEsperado(double valor){
		this.formaCalculoCambioEsperado = FORMA_CALCULOCAMBIOESPERADO_VALORESPECIFICADO;
		this.valor = valor;
	}
	
	/**
	 * Crea un objeto que define el calculo del cambio esperado como la desviacion estandar
	 * obtenida al utilizar EWMA.
	 * @param lambda
	 * @param numobservaciones
	 * @param coeficienteconfianza
	 * @throws DatoInvalidoExcepcion Si el numero de observaciones es igual o menor que 0.
	 */
	public DefinidorCalculoCambioEsperado(double lambda, int numobservaciones,double coeficienteconfianza, byte tipodiferencia, int longperiodo) throws DatoInvalidoExcepcion{
		
		if (numobservaciones<=0)
			throw new DatoInvalidoExcepcion("Numero de observaciones igual o menor que 0.");
		
		this.formaCalculoCambioEsperado = FORMA_CALCULOCAMBIOESPERADO_EWMA;
		this.lambda = lambda;
		this.numobservaciones = numobservaciones;
		this.coeficienteconfianza = coeficienteconfianza;
                this.tipodiferencia = tipodiferencia;
		this.longperiodo = longperiodo;
	}
	
	/**
	 * Crea un objeto que define el calculo del cambio esperado como la desviacion estandar
	 * de la serie de valores.
	 * @param numobservaciones
	 * @param coeficienteconfianza
	 * @throws DatoInvalidoExcepcion Si el numero de observaciones es igual o menor que 0.
	 */
	public DefinidorCalculoCambioEsperado(int numobservaciones,	double coeficienteconfianza) throws DatoInvalidoExcepcion{
		
		if (numobservaciones<=0)
			throw new DatoInvalidoExcepcion("Numero de observaciones igual o menor que 0.");
		
		this.formaCalculoCambioEsperado = FORMA_CALCULOCAMBIOESPERADO_NORMAL;
		this.numobservaciones = numobservaciones;
		this.coeficienteconfianza = coeficienteconfianza;
	}
	
	/**
	 * Crea un objeto que define el calculo del cambio esperado utilizando el metodo de las diferencias.
	 * @param tipodiferencia Especifica si el tipo de diferencia a utilizar es la aritmetica o la logaritmica.
	 * @param longperiodo longitud del intervalo de comparacion.
	 * @param numobservaciones
	 * @param coeficienteconfianza
	 * @throws DatoInvalidoExcepcion Si el numero de observaciones o la longitud del intervalo es igual o menor que 0,
	 * o si la diferencia especificada no es valida.
	 */
	public DefinidorCalculoCambioEsperado(byte tipodiferencia, int longperiodo,	int numobservaciones, double coeficienteconfianza,Boolean sumarPromedio) throws DatoInvalidoExcepcion{
		
		if (numobservaciones<=0)
			throw new DatoInvalidoExcepcion("Numero de observaciones igual o menor que 0.");
		
		if (longperiodo<=0)
			throw new DatoInvalidoExcepcion("Longitud del periodo igual o menor que 0.");
				
		if (tipodiferencia != DefinidorCalculoCambioEsperado.DIF_ARITMETICA 
				&& tipodiferencia != DefinidorCalculoCambioEsperado.DIF_LOGARITMICA
                                /*
                                 * Modificado por Cristhiam Reina
                                 * 5 de agosto 2011
                                 * Nueva Condicion
                                 */
                                && tipodiferencia  != DefinidorCalculoCambioEsperado.DIF_GEOMETRICA
                               /*
                                 * Modificado por Eliecer Cortes
                                 * Sept 2 de 2011
                                 * Nueva Condicion
                                 */
                                && tipodiferencia  != DefinidorCalculoCambioEsperado.NO_CALCULAR_DIF)
			throw new DatoInvalidoExcepcion("El tipo de diferencia con el que se debe calcular el cambio esperado no es valido.");

        if(sumarPromedio!=null){
            this.formaCalculoCambioEsperado = sumarPromedio?FORMA_CALCULOCAMBIOESPERADO_ELIECER:FORMA_CALCULOCAMBIOESPERADO_ELIECER_NO_SUMAR_PROMEDIO;
        }else{
            this.formaCalculoCambioEsperado =FORMA_CALCULOCAMBIOESPERADO_ELIECER_NO_SUMAR_PROMEDIO_MAX_OBSERVACION;
        }
		this.numobservaciones = numobservaciones;
		this.coeficienteconfianza = coeficienteconfianza;
		this.tipodiferencia = tipodiferencia;
		this.longperiodo = longperiodo;
	}

	public DefinidorCalculoCambioEsperado(int numobservaciones,  double coeficienteconfianza, byte tipodiferencia, int longperiodo)
                throws DatoInvalidoExcepcion{

            if (numobservaciones<=0)
			throw new DatoInvalidoExcepcion("Numero de observaciones igual o menor que 0.");

            this.formaCalculoCambioEsperado = FORMA_VALORACION_HISTORICA;
            this.numobservaciones = numobservaciones;
            this.coeficienteconfianza = coeficienteconfianza;
            this.tipodiferencia = tipodiferencia;
            this.longperiodo = longperiodo;
        }

        public DefinidorCalculoCambioEsperado(int numobservaciones, byte tipodiferencia, int longperiodo)
                throws DatoInvalidoExcepcion{

            if (numobservaciones<=0)
			throw new DatoInvalidoExcepcion("Numero de observaciones igual o menor que 0.");

            this.formaCalculoCambioEsperado = FORMA_REGRESION_LINIAL;
            this.numobservaciones = numobservaciones;
            this.tipodiferencia = tipodiferencia;
            this.longperiodo = longperiodo;
        }
	/**
	 * @param valor  The valor to set.
	 * @uml.property  name="valor"
	 */
	public void setValor(double valor){
		this.valor = valor;
	}
	
	/**
	 * @return  Returns the valor.
	 * @uml.property  name="valor"
	 */
	public double getValor() {
		return valor;
	}
	
	/**
	 * @param numdias  The numdias to set.
	 * @uml.property  name="numdias"
	 */
	public void setNumdias(int numdias){
		this.numdias = numdias;
	}
	
	/**
	 * @return  Returns the numdias.
	 * @uml.property  name="numdias"
	 */
	public int getNumdias(){
		return numdias;
	}

	/**
	 * @param numobservaciones  The numobservaciones to set.
	 * @uml.property  name="numobservaciones"
	 */
	public void setNumobservaciones(int numobservaciones){
		this.numobservaciones = numobservaciones;
	}
	
	/**
	 * @return  Returns the numobservaciones.
	 * @uml.property  name="numobservaciones"
	 */
	public int getNumobservaciones() {
		return numobservaciones;
	}
	
	/**
	 * @param coeficienteconfianza  The coeficienteconfianza to set.
	 * @uml.property  name="coeficienteconfianza"
	 */
	public void setCoeficienteconfianza(double coeficienteconfianza){
		this.coeficienteconfianza = coeficienteconfianza;
	}
	
	/**
	 * @return  Returns the coeficienteconfianza.
	 * @uml.property  name="coeficienteconfianza"
	 */
	public double getCoeficienteconfianza() {
		return coeficienteconfianza;
	}

	/**
	 * @param lambda  The lambda to set.
	 * @uml.property  name="lambda"
	 */
	public void setLambda(double lambda){
		this.lambda = lambda;
	}
	
	/**
	 * @return  Returns the lambda.
	 * @uml.property  name="lambda"
	 */
	public double getLambda() {
		return lambda;
	}

	/**
	 * @param tipodiferencia  The tipodiferencia to set.
	 * @uml.property  name="tipodiferencia"
	 */
	public void setTipodiferencia(byte tipodiferencia) throws DatoInvalidoExcepcion{
		if (tipodiferencia != DefinidorCalculoCambioEsperado.DIF_ARITMETICA 
				&& tipodiferencia != DefinidorCalculoCambioEsperado.DIF_LOGARITMICA

                                /*
                                 * Modificado por Cristhiam Reina
                                 * 5 de agosto 2011
                                 * Nueva Condicion
                                 */
                                && tipodiferencia != DefinidorCalculoCambioEsperado.DIF_GEOMETRICA
                               /*
                                 * Modificado por Eliecer Cortes
                                 * Sept 2 de 2011
                                 * Nueva Condicion
                                 */
                                && tipodiferencia  != DefinidorCalculoCambioEsperado.NO_CALCULAR_DIF)

			throw new DatoInvalidoExcepcion("El tipo de diferencia con el que se debe calcular el cambio esperado no es valido.");

		this.tipodiferencia = tipodiferencia;
	}
	
	/**
	 * @return  Returns the tipodiferencia.
	 * @uml.property  name="tipodiferencia"
	 */
	public byte getTipodiferencia() {
		return tipodiferencia;
	}

	/**
	 * @param longperiodo  The longperiodo to set.
	 * @uml.property  name="longperiodo"
	 */
	public void setLongperiodo(int longperiodo){
		this.longperiodo = longperiodo;
	}
	
	/**
	 * @return  Returns the longperiodo.
	 * @uml.property  name="longperiodo"
	 */
	public int getLongperiodo() {
		return longperiodo;
	}
	
	/**
	 * @return  Returns the formaCalculoCambioEsperado.
	 * @uml.property  name="formaCalculoCambioEsperado"
	 */
	public byte getFormaCalculoCambioEsperado() {
		return formaCalculoCambioEsperado;
	}
	
}

